/**
 * Created by liyl on 24/09/2020.
 */
import { VuexModule, Module, Mutation, getModule, Action } from 'vuex-module-decorators'
import store from '@/store'
import router from '@/router/handleRoute'
import { Notification } from 'element-ui'
import { commonAction, handleLabelData } from '@/utils/common'
import { microRouter, instance } from '@/microPage/webchat/main'
// import { microRouter } from '@/microPage/webchat/main'
import { WebchatModule } from '@/store/modules/webchat'
import { noticeConfigModule } from '@/store/modules/config/notice'
import Vue from 'vue'
export interface CommonState {
  containerType: any
  navMenuState: boolean,
  isSignOut: boolean,
  session: any,
  preLogin: any,
  initConfig: any,
  publicCache: any,
  audioObj: any,
  agentes: any,
  elNotification: any
}

export interface SetPublic {
  data: any,
  type: string,
  hasObj: boolean
  isNeedTree?: boolean
}
@Module({ dynamic: true, name: 'common', store, namespaced: false })
class Common extends VuexModule implements CommonState {
  public diffTime = 0 // 本地时间跟服务器的时间差
  public containerType = 'v7Cloud'
  public navMenuState = true
  public isSignOut: boolean = false // 是否是退出
  public audioObj = { audioUrl: '', currentId: '' } // 全局的audio,用于播放录音 && 播放进度
  public session: any = {}
  public elNotification: any = {} // 通知对象
  public agentes = {}
  public preLogin = {} // 登录前获取的信息，目前只有pk
  public initConfig = {} // 初始化加载页面的第一个请求，获取pushserve等信息
  public tabList = {} // 右侧tab列表
  public dk = '' // 对接参数加密密钥
  public mpInfo = {} // mp的登录信息
  public publicCache = { // 通用类
    customerInputConfig: [], // 客户录入面板配置
    customerDetailConfig: [], // 客户详情面板配置
    customerAllFields: [], // 客户字段
    customerAllLabels: [], // 客户标签
    customerAllLabelsObj: {}, // 以_id为key的数据（客户标签）
    customerImports: [], // 客户导入
    region: [], // 省市区（带_id）
    cdrRegion: [], // 搜索
    loginMenuList: [], // 一级菜单列表
    userList: [], // 座席列表（所有座席）
    userListObj: {}, // 以_id做为key的数据（所有座席）
    userListEnable: [], // 座席列表（启用的座席）
    queueList: [], // 技能组列表
    queueListObj: {}, // 以_id做为key的数据
    licenceList: [], // licence版本列表
    licenceListObj: {},
    roleList: [], // 角色列表
    roleListObj: {}, // 以_id做为key的数据
    ticketList: [], // mp工单模板列表
    ticketListObj: {}, // 以_id做为key的数据
    customerList: {}, // mp客户模板字段对应关系列表
    commonAppIdList: [], // 常用应用列表
    // 通话类
    phonebarList: [], // 电话条状态
    phoneSatisfactionList: [], // 满意度配置列表
    timeConditionList: [], // 时间条件列表
    voiceLibraryList: [], // 语音库列表
    serviceNumberList: [], // 服务号列表
    previewDialoutAgentList: [], // 预览外呼权限的座席
    ivrList: [], // 语音导航列表
    ivrListObj: [], // 以_id作为key的语音导航的数据
    // 在线类
    channelList: [], // 渠道列表
    channelListObj: {}, // 以_id作为key的数据
    satisfactionList: [], // 满意度列表
    satisfactionListObj: {}, // 以_id作为key 的数据
    cssList: [], // 样式列表
    sdkCssList: [], // sdk列表
    sdkCssListObj: {}, // 以_id作为key的数据
    wxsdkCssList: [], // 小程序sdk 样式列表
    wxsdkCssListObj: {},
    cssListObj: {}, // 以_id作为key的数据
    processList: [], // 流程列表
    processListObj: {}, // 以_id作为key的数据
    webchatStatusList: [], // 在线自定义状态列表
    plarform: [], // 在线渠道来源列表
    plarformObj: {}, // 以_id作为key在线渠道来源
    seoSource: [], // 会话来源搜索
    status: [], // 会话状态
    statusObj: {},
    sessionType: [], // 会话类型
    sessionTypeObj: {}, // 以_id作为key的会话类型数据
    finishKey: [], // 在线结束会话类型列表
    sessionTags: [], // 在线会话标签
    sessionTagsTreeObj: {}, // 在线会话标签
    globalConfig: [], // 在线全局其他设置
    departmentList: [], // 部门列表
    departmentListObj: {}, // 以_id作为key的数据
    departmentTree: null, // 部门树
    satisfactionName: [] // 满意度标签
  } // 公共缓存

  public tabBasicData = {} // 处理tab丢失问题

  @Mutation
  public setTabBisacByType ({ type, data }) {
    this.tabBasicData[type] = data
  }

  @Action
  public async publicAction (parame: object) {
    return commonAction(parame).then(resp => {
      return resp
    })
  }

  @Action
  public async getMpInfo (parame: object) {
    if (Object.keys(this.mpInfo).length <= 0) {
      return commonAction(parame).then(resp => {
        if (resp && resp.success) {
          this.setMpInfo(resp.data || {})
        }
        return resp
      })
    } else {
      return this.setMpInfo(this.mpInfo)
    }
  }

  @Mutation
  public setDiffTime (data: number) {
    this.diffTime = data
  }

  @Mutation
  public newSetPubCache (obj: any) {
    const levels = obj.reslevel && obj.reslevel.indexOf('.') > -1 ? obj.reslevel.split('.') : [obj.reslevel] // 层级拆分
    let resData = obj.resp
    levels.map(item => {
      resData = resData[item]
    })
    this.publicCache[obj.type] = resData // 赋值
    if (obj.hasObj) {
      const newObj = {}
      if (resData && Array.isArray(resData)) {
        resData.map(item => {
          newObj[item._id] = item
        })
      }
      this.publicCache[obj.type + 'Obj'] = newObj // 以id为key的数据
    }
  }

  @Mutation
  public setMpInfo (data: any) {
    this.mpInfo = data
  }

  @Mutation
  public setNavMenuState () {
    this.navMenuState = !this.navMenuState
    window.sessionStorage.setItem('navMenuState', JSON.stringify(this.navMenuState))
  }

  @Mutation
  public setIsSignOut () {
    this.isSignOut = !this.isSignOut
  }

  @Mutation
  public SET_DK (data) {
    this.dk = data
  }

  @Mutation
  public getNavMenuState () {
    const navMenuState = window.sessionStorage.getItem('navMenuState') || 'true'
    this.navMenuState = JSON.parse(navMenuState)
  }

  @Mutation
  public setUserInfo (data: any) {
    const agents = this.agentes
    const agentItem = agents[data._id]
    if (agentItem) {
      agentItem.userIcon = data.userIcon
    }
    for (const key in data) {
      if (data[key] !== undefined) {
        // @ts-ignore: Unreachable code error
        this.session.user[key] = data[key]
      }
    }
  }

  @Mutation
  public setAudioObj (data: any) {
    Object.keys(data).forEach(key => {
      if (this.audioObj[key] !== undefined) {
        this.audioObj[key] = data[key]
      }
    })
  }

  @Mutation
  public setSession (data: any) {
    this.session = data
  }

  @Mutation
  public setPreLogin (data: string) {
    this.preLogin = data
  }

  @Mutation
  public setInitConfig (data: string) {
    this.initConfig = data
  }

  @Mutation
  public updateLoginMenuList (data: any) {
    if (this.publicCache.loginMenuList) {
      // @ts-ignore: Unreachable code error
      const menuIndex = this.publicCache.loginMenuList.indexOf(data.menu)
      if (menuIndex > -1 && data.type === 'delete') { // 删除
        this.publicCache.loginMenuList.splice(menuIndex, 1)
      } else if (data.type === 'add') { // 新增
        // @ts-ignore: Unreachable code error
        this.publicCache.loginMenuList.push(data.menu)
      }
    }
  }

  @Mutation
  public setPublicCache (obj: SetPublic) {
    // 对departmentList 进行平铺
    if (obj.type === 'departmentList') {
      const departmentObj: any = {}
      const flatarr = (arr) => {
        console.log(arr)
        arr.map(v => {
          departmentObj[v._id] = { name: v.name, _id: v._id }
          if (v.children && v.children.length > 0) {
            flatarr(v.children)
          }
        })
      }
      flatarr(obj.data)
      this.publicCache.departmentListObj = departmentObj
      return
    }
    const enableType = ['userList'] // 需要过滤
    if (obj.hasObj) {
      const newObj: any = {}
      const enableArr: any[] = []
      if (obj.data.length > 0) {
        obj.data.forEach((item: any) => {
          newObj[item._id] = JSON.parse(JSON.stringify(item))
          if (enableType.indexOf(obj.type) > -1 && item.status === 'enable') {
            enableArr.push(item)
          }
          if (['userList'].includes(obj.type)) { // 为座席增加name拼接，回显使用
            newObj[item._id] = {
              ...newObj[item._id],
              name: `${item.agentName} [${item.agentNumber}]`
            }
          }
        })
        if (enableType.indexOf(obj.type) > -1) { // 过滤启用状态的数据
          this.publicCache[obj.type + 'Enable'] = enableArr
        }
      }
      this.publicCache[obj.type + 'Obj'] = newObj // 以id为key的数据
    }
    if (obj.isNeedTree && obj.data.tree) {
      let newObj: any = {}
      const treeData = obj.data.tree || []
      newObj = handleLabelData(treeData, {})
      this.publicCache[obj.type + 'TreeObj'] = newObj
    }
    this.publicCache[obj.type] = obj.data // 普通类型的所有数据
  }

  @Mutation
  public SETTABLIST ({ tabList, module }) {
    Vue.set(this.tabList, module, tabList)
  }

  @Mutation
  public NOTIFY ({ title, message, options, routePath, notifyData }) {
    // 先检查浏览器是否支持
    this.elNotification = Notification
    const that = this
    if (!window.Notification) {
      console.log('浏览器不支持通知');
      this.elNotification({
        title,
        message,
        position: 'bottom-right',
        duration: 10000,
        onClick () {
          notifyClick(routePath, notifyData)
          this.close()
        }
      })
    } else {
      // 检查用户曾经是否同意接受通知
      if (window.Notification.permission === 'granted') {
        const notify = new window.Notification(title, options) // 显示通知
        notify.onclick = () => {
          window.focus()
          notifyClick(routePath, notifyData)
        }
      } else if (window.Notification.permission === 'default') {
        // 用户还未选择，可以询问用户是否同意发送通知
        window.Notification.requestPermission().then(permission => {
          if (permission === 'granted') {
            const notify = new window.Notification(title, options) // 显示通知
          } else {
            // denied
            this.elNotification({
              title,
              message,
              position: 'bottom-right',
              duration: 10000,
              onClick () {
                notifyClick(routePath, notifyData)
                this.close()
              }
            })
            console.log('用户拒绝授权 不能显示通知')
          }
        });
      } else {
        // denied 用户拒绝
        console.log('用户曾经拒绝显示通知');
        this.elNotification({
          title,
          message,
          position: 'bottom-right',
          duration: 10000,
          onClick () {
            notifyClick(routePath, notifyData)
            this.close()
          }
        })
      }
    }
    const notifyClick = (route: any, data: any) => { // 通知点击事件
      if (route.indexOf('webchat_todo') > -1) { // 在线
        const sessionId = route.split('/')[4]
        if (WebchatModule.webchatList.webchat_todo) { // 判断当前要跳转的会话是否纯在会话列表中
          const currentSession = WebchatModule.webchatList.webchat_todo.find((item: any) => {
            return item._id === sessionId
          })
          const newRouter = this.containerType && this.containerType === 'micro' ? microRouter : router
          if (currentSession) {
            newRouter.push({ path: route })
          } else {
            newRouter.push({ path: '/im_workBench/index/webchat_todo/empty' })
          }
        }
      } else if (route.indexOf('call') > -1) { // 通话
        router.push({ path: route })
      } else if (data && data.bodyType === 'mpNotice') { // mp 工单和客户的消息
        router.push(route)
        Vue.prototype.$bus.$emit('updateMpRecord', data)
      } else if (route.indexOf('home') > -1) {
        router.push({ path: route })
        noticeConfigModule.AddRefreshNotice()
      }
    }
  }

  @Mutation
  public SET_CURRENT_ENV () {
    if (process.env.VUE_APP_ENTRY !== 'main') {
      this.containerType = 'micro'
    }
  }

  // 设置部门列表
  @Mutation
  public SET_DEPRTMENT_TREE (tree) {
    this.publicCache.departmentTree = tree
  }

  /**
   * 获取部门列表，使用缓存
   * @param forceUpdate 是否强制获取数据
   * @returns
   */
  @Action
  public async getDepartmentTree (forceUpdate: boolean = false) {
    if (!this.publicCache.departmentTree || forceUpdate) {
      return commonAction({ url: '/base/action/department/query', method: 'POST' }).then(resp => {
        if (resp && resp.success) {
          this.SET_DEPRTMENT_TREE(resp.data)
          return resp.data
        }
      })
    } else {
      return this.publicCache.departmentTree
    }
  }
}

export const CommonModule = getModule(Common)
